/**
 * Copyright (c) 2018-2023, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contains: 
 *
 * Change Logs:
 * Date           Author            Notes
 * 2023-07-18     Shiroko           Init
 */
#ifndef __DRIVERS_VIRTIO_VIRTIO_MMIO_PRIVATE_H__
#define __DRIVERS_VIRTIO_VIRTIO_MMIO_PRIVATE_H__

#include <nxos.h>

/* VIRTIO MMIO Definitions */
/*
 * MMIO Specification:
 * https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html#x1-1650002
 */
#define VIRTIO_MMIO_MAGIC    0x74726976 // "virt"

/*
 * MMIO Device Register Offsets
 */
#define VIRTIO_MMIO_REG_OFFSET_MAGIC_VALUE          0x000 // [R]  Magic value
#define VIRTIO_MMIO_REG_OFFSET_VERSION              0x004 // [R]  Version
#define VIRTIO_MMIO_REG_OFFSET_DEVICE_ID            0x008 // [R]  Device ID
#define VIRTIO_MMIO_REG_OFFSET_VENDOR_ID            0x00c // [R]  Vendor ID
#define VIRTIO_MMIO_REG_OFFSET_DEVICE_FEATURES      0x010 // [R]  Device Features
#define VIRTIO_MMIO_REG_OFFSET_DEVICE_FEATURES_SEL  0x014 // [W]  Device Features selector
#define VIRTIO_MMIO_REG_OFFSET_DRIVER_FEATURES      0x020 // [W]  Driver Features
#define VIRTIO_MMIO_REG_OFFSET_DRIVER_FEATURES_SEL  0x024 // [W]  Driver Features selector
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_SEL            0x030 // [W]  Queue selector
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_NUM_MAX        0x034 // [R]  Queue max size
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_NUM            0x038 // [W]  Queue size
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_READY          0x044 // [RW] Queue Ready
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_NOTIFY         0x050 // [W]  Queue notifier
#define VIRTIO_MMIO_REG_OFFSET_INTERRUPT_STATUS     0x060 // [R]  Interrupt Status
#define VIRTIO_MMIO_REG_OFFSET_INTERRUPT_ACK        0x064 // [W]  Interrupt ACK
#define VIRTIO_MMIO_REG_OFFSET_STATUS               0x070 // [RW] Device status
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DESC_LOW       0x080 // [W] 64bit Descriptor area physical address
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DESC_HIGH      0x084
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DRIVER_LOW     0x090 // [W] 64bit Driver area physical address
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DRIVER_HIGH    0x094
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DEVICE_LOW     0x0a0 // [W] 64bit Device area physical address
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_DEVICE_HIGH    0x0a4
#define VIRTIO_MMIO_REG_OFFSET_QUEUE_RESET          0x0c0 // [RW] Virtio Queue Reset Bit
#define VIRTIO_MMIO_REG_OFFSET_CONFIG_GENERATION    0x0fc // [R] Configuration atomicity value
#define VIRTIO_MMIO_REG_OFFSET_DEVICE_CONFIG        0x100 // [RW] Start of device-specific config space

#define MMIO_READ(type, addr) (*(volatile type *)((NX_UArch)(addr)))
#define MMIO_WRITE(type, addr, value)   \
        do { (*(volatile type *)((NX_UArch)(addr))) = ((type)(value)); }while(0)

#define VIRTIO_MMIO_REG_READ(field, base)   MMIO_READ(NX_U32, (base) + VIRTIO_MMIO_REG_OFFSET_##field)
#define VIRTIO_MMIO_REG_WRITE(field, base, value) MMIO_WRITE(NX_U32, (base) + VIRTIO_MMIO_REG_OFFSET_##field, value)

/*
 * Helper struct
 */

struct VirtioMMIOExtension
{
    VirtioMMIODeviceInfo info;
    NX_Addr baseAddr;
};
typedef struct VirtioMMIOExtension VirtioMMIOExtension;

#endif // __DRIVERS_VIRTIO_VIRTIO_MMIO_PRIVATE_H__
